---
title: Authentication Operations
label: Operations
order: 20
desc: Enabling Authentication automatically makes key operations available such as Login, Logout, Verify, Unlock, Reset Password and more.
keywords: authentication, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
---

Enabling [Authentication](./overview) on a [Collection](../configuration/collections) automatically exposes additional auth-based operations in the [Local API](../local-api/overview), [REST API](../rest-api/overview), and [GraphQL API](../graphql/overview).

## Access

The Access operation returns what a logged in user can and can't do with the collections and globals that are registered via your config. This data can be immensely helpful if your app needs to show and hide certain features based on [Access Control](../access-control/overview), just as the [Admin Panel](../admin/overview) does.

**REST API endpoint**:

`GET http://localhost:3000/api/access`

Example response:

```ts
{
  canAccessAdmin: true,
  collections: {
    pages: {
      create: {
        permission: true,
      },
      read: {
        permission: true,
      },
      update: {
        permission: true,
      },
      delete: {
        permission: true,
      },
      fields: {
        title: {
          create: {
            permission: true,
          },
          read: {
            permission: true,
          },
          update: {
            permission: true,
          },
        }
      }
    }
  }
}
```

**Example GraphQL Query**:

```graphql
query {
  Access {
    pages {
      read {
        permission
      }
    }
  }
}
```

Document access can also be queried on a collection/global basis. Access on a global can queried like `http://localhost:3000/api/global-slug/access`, Collection document access can be queried like `http://localhost:3000/api/collection-slug/access/:id`.

## Me

Returns either a logged in user with token or null when there is no logged in user.

**REST API endpoint**:

`GET http://localhost:3000/api/[collection-slug]/me`

Example response:

```ts
{
  user: { // The JWT "payload" ;) from the logged in user
    email: 'dev@payloadcms.com',
    createdAt: "2020-12-27T21:16:45.645Z",
    updatedAt: "2021-01-02T18:37:41.588Z",
    id: "5ae8f9bde69e394e717c8832"
  },
  token: '34o4345324...', // The token that can be used to authenticate the user
  exp: 1609619861, // Unix timestamp representing when the user's token will expire
}
```

**Example GraphQL Query**:

```graphql
query {
  me[collection-singular-label] {
    user {
      email
    }
    exp
  }
}
```

## Login

Accepts an `email` and `password`. On success, it will return the logged in user as well as a token that can be used to authenticate. In the GraphQL and REST APIs, this operation also automatically sets an HTTP-only cookie including the user's token. If you pass a `res` to the Local API operation, Payload will set a cookie there as well.

**Example REST API login**:

```ts
const res = await fetch('http://localhost:3000/api/[collection-slug]/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    email: 'dev@payloadcms.com',
    password: 'this-is-not-our-password...or-is-it?',
  }),
})

const json = await res.json()

// JSON will be equal to the following:
/*
{
  user: {
    email: 'dev@payloadcms.com',
    createdAt: "2020-12-27T21:16:45.645Z",
    updatedAt: "2021-01-02T18:37:41.588Z",
    id: "5ae8f9bde69e394e717c8832"
  },
  token: '34o4345324...',
  exp: 1609619861
}
*/
```

**Example GraphQL Mutation**:

```graphql
mutation {
  login[collection-singular-label](email: "dev@payloadcms.com", password: "yikes") {
    user {
      email
    }
    exp
    token
  }
}
```

**Example Local API login**:

```ts
const result = await payload.login({
  collection: '[collection-slug]',
  data: {
    email: 'dev@payloadcms.com',
    password: 'get-out',
  },
})
```

## Logout

As Payload sets HTTP-only cookies, logging out cannot be done by just removing a cookie in JavaScript, as HTTP-only cookies are inaccessible by JS within the browser. So, Payload exposes a `logout` operation to delete the token in a safe way.

**Example REST API logout**:

```ts
const res = await fetch('http://localhost:3000/api/[collection-slug]/logout', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
})
```

**Example GraphQL Mutation**:

```
mutation {
  logout[collection-singular-label]
}
```

## Refresh

Allows for "refreshing" JWTs. If your user has a token that is about to expire, but the user is still active and using the app, you might want to use the `refresh` operation to receive a new token by executing this operation via the authenticated user.

This operation requires a non-expired token to send back a new one. If the user's token has already expired, you will need to allow them to log in again to retrieve a new token.

If successful, this operation will automatically renew the user's HTTP-only cookie and will send back the updated token in JSON.

**Example REST API token refresh**:

```ts
const res = await fetch('http://localhost:3000/api/[collection-slug]/refresh-token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
})

const json = await res.json()

// JSON will be equal to the following:
/*
{
  user: {
    email: 'dev@payloadcms.com',
    createdAt: "2020-12-27T21:16:45.645Z",
    updatedAt: "2021-01-02T18:37:41.588Z",
    id: "5ae8f9bde69e394e717c8832"
  },
  refreshedToken: '34o4345324...',
  exp: 1609619861
}
*/
```

**Example GraphQL Mutation**:

```
mutation {
  refreshToken[collection-singular-label] {
    user {
      email
    }
    refreshedToken
  }
}
```

## Verify by Email

If your collection supports email verification, the Verify operation will be exposed which accepts a verification token and sets the user's `_verified` property to `true`, thereby allowing the user to authenticate with the Payload API.

**Example REST API user verification**:

```ts
const res = await fetch(`http://localhost:3000/api/[collection-slug]/verify/${TOKEN_HERE}`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
})
```

**Example GraphQL Mutation**:

```graphql
mutation {
  verifyEmail[collection-singular-label](token: "TOKEN_HERE")
}
```

**Example Local API verification**:

```ts
const result = await payload.verifyEmail({
  collection: '[collection-slug]',
  token: 'TOKEN_HERE',
})
```

**Note:** the token you need to pass to the `verifyEmail` function is unique to verification and is not the same as the token that you can retrieve from the `forgotPassword` operation. It can be found on the user document, as a hidden `_verificationToken` field. If you'd like to retrieve this token, you can use the Local API's `find` or `findByID` methods, setting `showHiddenFields: true`.

**Note:** if you do not have a `config.serverURL` set, Payload will attempt to create one for you if the user was created via REST or GraphQL by looking at the incoming `req`. But this is not supported if you are creating the user via the Local API's `payload.create()` method. If this applies to you, and you do not have a `serverURL` set, you may want to override your `verify.generateEmailHTML` function to provide a full URL to link the user to a proper verification page.

## Unlock

If a user locks themselves out and you wish to deliberately unlock them, you can utilize the Unlock operation. The [Admin Panel](../admin/overview) features an Unlock control automatically for all collections that feature max login attempts, but you can programmatically unlock users as well by using the Unlock operation.

To restrict who is allowed to unlock users, you can utilize the [`unlock`](../access-control/collections#unlock) access control function.

**Example REST API unlock**:

```ts
const res = await fetch(`http://localhost:3000/api/[collection-slug]/unlock`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
})
```

**Example GraphQL Mutation**:

```
mutation {
  unlock[collection-singular-label]
}
```

**Example Local API unlock**:

```ts
const result = await payload.unlock({
  collection: '[collection-slug]',
})
```

## Forgot Password

Payload comes with built-in forgot password functionality. Submitting an email address to the Forgot Password operation will generate an email and send it to the respective email address with a link to reset their password.

The link to reset the user's password contains a token which is what allows the user to securely reset their password.

By default, the Forgot Password operations send users to the [Admin Panel](../admin/overview) to reset their password, but you can customize the generated email to send users to the frontend of your app instead by [overriding the email HTML](/docs/authentication/email#forgot-password).

**Example REST API Forgot Password**:

```ts
const res = await fetch(`http://localhost:3000/api/[collection-slug]/forgot-password`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    email: 'dev@payloadcms.com',
  }),
})
```

**Example GraphQL Mutation**:

```
mutation {
  forgotPassword[collection-singular-label](email: "dev@payloadcms.com")
}
```

**Example Local API forgot password**:

```ts
const token = await payload.forgotPassword({
  collection: '[collection-slug]',
  data: {
    email: 'dev@payloadcms.com',
  },
  disableEmail: false, // you can disable the auto-generation of email via local API
})
```

<Banner type="info">
  **Note:** if you do not have a `config.serverURL` set, Payload will attempt to create one for you if the `forgot-password` operation was triggered via REST or GraphQL by looking at the incoming `req`. But this is not supported if you are calling `payload.forgotPassword()` via the Local API. If you do not have a `serverURL` set, you may want to override your `auth.forgotPassword.generateEmailHTML` function to provide a full URL to link the user to a proper reset-password page.
</Banner>

<Banner type="success">
  **Tip:**

  You can stop the reset-password email from being sent via using the local API. This is helpful if
  you need to create user accounts programmatically, but not set their password for them. This
  effectively generates a reset password token which you can then use to send to a page you create,
  allowing a user to "complete" their account by setting their password. In the background, you'd
  use the token to "reset" their password.
</Banner>

## Reset Password

After a user has "forgotten" their password and a token is generated, that token can be used to send to the reset password operation along with a new password which will allow the user to reset their password securely.

**Example REST API Reset Password**:

```ts
const res = await fetch(`http://localhost:3000/api/[collection-slug]/reset-password`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    token: 'TOKEN_GOES_HERE'
    password: 'not-today',
  }),
});

const json = await res.json();

// JSON will be equal to the following:
/*
{
  user: {
    email: 'dev@payloadcms.com',
    createdAt: "2020-12-27T21:16:45.645Z",
    updatedAt: "2021-01-02T18:37:41.588Z",
    id: "5ae8f9bde69e394e717c8832"
  },
  token: '34o4345324...',
  exp: 1609619861
}
*/
```

**Example GraphQL Mutation**:

```graphql
mutation {
  resetPassword[collection-singular-label](token: "TOKEN_GOES_HERE", password: "not-today")
}
```
